public class EditPlanEligibilityVF {

    private final Plan__c[] plan = new Plan__c[1];

    public String byRoleTitle {get; set;}
    public boolean roleDisabled {get; set;}
    public boolean titleDisabled {get; set;}
    public Integer removeEligibilityRow {get; set;}
    private Integer roleCount {get; set;}
    private Integer titleCount {get; set;}
    
    public List<Plan_Assignable__c> participantsList {get; set;}
    public Plan_Role__c[] planRoleList = new Plan_Role__c[]{};
    
    public Plan_Assignable__c pa {get; set;}
    private List<String> userTitleList = null;
    private Map<ID, UserRole> userRoleMap = null;
    private Map<ID, ID> planRoleMap = new Map<ID, ID>();
    private Map<ID, Plan_Assignable__c> checkParticipantsMap = new Map<ID, Plan_Assignable__c>(); 
    
    private List<RoleWrapper> rolesList = new List<RoleWrapper>();
    private List<RoleWrapper> rolesDupList = new List<RoleWrapper>();
    private List<TitleWrapper> titlesList = new List<TitleWrapper>();
    private List<TitleWrapper> titlesDupList = new List<TitleWrapper>();

    public EditPlanEligibilityVF(ApexPages.StandardController myController)
    {
        this.plan[0] = (Plan__c)myController.getRecord();
        byRoleTitle = 'byTitle';
        roleDisabled = titleDisabled = false;
        roleCount = titleCount = 0;
        participantsList = null;
        setUserRoles();
        Plan__c[] plan = [select Type__c from Plan__c where id = :plan[0].id];
        
        if(plan.size() > 0 && plan[0].Type__c == 'Role')
            byRoleTitle = 'byRole';
            
        planRoleList = [select id, RoleId__c, RoleTitle__c, Description__c from Plan_Role__c where plan__c = :plan[0].id];
        for(Plan_Role__c pr: planRoleList)
        {
        	planRoleMap.put(pr.ID, pr.ID);	
        }
        
        if(planRoleList.size() > 0 && byRoleTitle == 'byTitle')
        {
            roleDisabled = !roleDisabled;
            for(Plan_Role__c pr: planRoleList)
            {
                TitleWrapper t = new TitleWrapper(titleCount++);
                t.selectedTitle = pr.RoleTitle__c;
                titlesList.add(t);  
            }
        }        
        else if(planRoleList.size() > 0 && byRoleTitle == 'byRole')
        {
            titleDisabled = !titleDisabled;
            for(Plan_Role__c pr: planRoleList)
            {
                RoleWrapper r = new RoleWrapper(roleCount++);
                r.selectedRole = pr.RoleId__c;
                rolesList.add(r);   
            }
        }        
        else
        {
            titlesList.add(new TitleWrapper(titleCount++));
            titlesList.add(new TitleWrapper(titleCount++));
            titlesList.add(new TitleWrapper(titleCount++));
            titlesList.add(new TitleWrapper(titleCount++));
            titlesList.add(new TitleWrapper(titleCount++));
        }
        
        participantsList = [select Participant__c, Role_ID__c, Role_Title__c, Effective_Start_Date__c, Effective_End_Date__c from Plan_Assignable__c where Plan_Role__c in :planRoleMap.keySet() limit 1000];
        for(Plan_Assignable__c pa: participantsList)
        {
        	checkParticipantsMap.put(pa.Participant__c, pa);
        }
        
        if(participantsList.size() == 0)
        	participantsList = null;
    }//end of Constructor
    
    public void setUserRoles()
    {
        userRoleMap = new Map<ID, UserRole>();
        for(UserRole[] uRoleList: [select Id, Name, Rollupdescription from UserRole order by Name])
        {
            for(UserRole ur: uRoleList)
                userRoleMap.put(ur.id, ur);
            if(userRoleMap.size() >= 1000)
                break;
        }
    }

    public PageReference addEligibility()
    {
        if(byRoleTitle == 'byTitle')
            titlesList.add(new TitleWrapper(titleCount++));
        else 
            rolesList.add(new RoleWrapper(roleCount++));
        return null;
    }    

    public PageReference saveEligibility()
    {
    	try
    	{
    		planRoleList.clear();
    		Map<Id, Id> deletedPlanRoles = new Map<Id, Id>();
	        for(Plan_Role__c[] pRole: [select id from Plan_Role__c where plan__c = :plan[0].id])
	        {
	        	for(Plan_Role__c pr: pRole)
	        		deletedPlanRoles.put(pr.id, pr.id);

		        for(Plan_Assignable__c[] pAssignable: [select id from Plan_Assignable__c where plan_role__c in :deletedPlanRoles.keyset()])
		            delete pAssignable;
		        deletedPlanRoles.clear();
	            delete pRole;
	        }

	        
	        Plan__c[] plan = [select Id, Type__c from Plan__c where id = :plan[0].id];
	        if(byRoleTitle == 'byRole')
	        {
	            Map<ID, ID> tempMap = new Map<ID, ID>();
	            for(RoleWrapper rw: rolesList)
	            {
                    tempMap.put(rw.selectedRole, rw.selectedRole);
	            }
	            if(plan.size() > 0)
	            {
	                plan[0].Type__c = 'Role';
	                update plan;
	            }
	            
	            if(tempMap.size() > 0)
	            {
	                List<String> selectedRoleList = tempMap.values();
	                Plan_Role__c planRole = null;
	                UserRole ur = null;
	                for(ID roleId : selectedRoleList)
	                {
	                    if((ur = userRoleMap.get(roleId)) != null)
	                    {
	                        planRole = new Plan_Role__c(RoleID__c = roleId, plan__c = plan[0].Id, RoleTitle__c = ur.Name, Description__c = ur.RollupDescription);
	                        planRoleList.add(planRole);
	                    }
	                }
	                if(planRoleList.size() > 0)
	                    insert planRoleList;

	                if(participantsList != null)
		        		for(Plan_Role__c pr: planRoleList)
		        			for(Plan_Assignable__c pa: participantsList)
		        				if(pr.RoleID__c == pa.Role_ID__c)
			        				pa.Plan_Role__c = pr.id;
	                
	            }           
	                
	        }
	        else
	        {
	            Map<String, String> tempMap = new Map<String, String>();
	            for(TitleWrapper tw: titlesList)
	            {
	                //if(tw.selectedTitle != 'select')
	                    tempMap.put(tw.selectedTitle, tw.selectedTitle);
	            }
	            
	            if(tempMap.size() > 0)
	            {
	                List<String> selectedTitleList = tempMap.values();
	                Plan_Role__c planRole = null;
	                for(String title : selectedTitleList)
	                {
	                    planRole = new Plan_Role__c(plan__c = plan[0].Id, RoleTitle__c = title);
	                    planRoleList.add(planRole);
	                }
	                if(planRoleList.size() > 0)
	                    insert planRoleList;

	                if(participantsList != null)
		        		for(Plan_Role__c pr: planRoleList)
		        			for(Plan_Assignable__c pa: participantsList)
		        				if(pr.RoleTitle__c == pa.Role_Title__c)
			        				pa.Plan_Role__c = pr.id;
	            }           
	            if(planRoleList.size() > 0 && plan.size() > 0)
	            {
	                plan[0].Type__c = 'Title';
	                update plan;
	            }
	            
	        }

            if(planRoleList.size() == 0)
            {
                plan[0].Type__c = '';
                update plan;
            }
	        
	        if(planRoleList.size() > 0 && participantsList != null && participantsList.size() > 0 && participantsList[0].Id == null)
	        	insert participantsList;
	        else if(planRoleList.size() > 0 && participantsList != null && participantsList.size() > 0) 
	        {
	        	List<Plan_Assignable__c> dupParticpantsList = new List<Plan_Assignable__c>();
	        	dupParticpantsList = participantsList.deepClone();
	        	participantsList.clear();
	        	for(Plan_Assignable__c p: dupParticpantsList)
	        	{
	        		Plan_Assignable__c pa = new Plan_Assignable__c(Participant__c = p.Participant__c, Role_ID__c = p.Role_ID__c, Role_Title__c = p.Role_Title__c, Plan_Role__c = p.Plan_Role__c, Effective_Start_Date__c = p.Effective_Start_Date__c, Effective_End_Date__c = p.Effective_End_Date__c);
	        		participantsList.add(pa);
	        	}
	        	insert participantsList;	
	        }
    	}
    	catch(Exception e)
    	{
    		if(e.getMessage().contains('ENTITY_IS_DELETED'))
	    		ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.info, 'Please update the Participants first and then save.'));
	    	else 
    		ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.info, e.getMessage()));
    	}
        return null;
    }    

    public PageReference cancelEligibility()
    {
        return null;
    }    
    
    public PageReference updateParticipants()
    {
    	try
    	{
    		if(rolesList.size() == 0 && titlesList.size() == 0)
    		{
	    		ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.info, 'Please define Eligibility and update the Participants.'));
	    		return null;
    		}	
    			
	    	Map<String, String> roleTitleMap = new Map<String, String>();
	    	if(participantsList != null)
	    		participantsList.clear();
	    	else
		    	participantsList = new Plan_Assignable__c[]{};
		    	
	    	Plan_Role__c[] pRoleList = [select Id, RoleID__c from Plan_Role__c where Plan__c = :plan[0].id];
	    	User[] usersList = null;
	    	if(byRoleTitle == 'byTitle')
	    	{
	            for(TitleWrapper tw: titlesList)
                    roleTitleMap.put(tw.selectedTitle, tw.selectedTitle);
	        	usersList = [select Id, Name, User.UserRole.Name, UserRoleId, User.Title from User u where u.Title in :roleTitleMap.keyset() limit 1000];
	    	}
	    	else
	    	{
	            for(RoleWrapper rw: rolesList)
                    roleTitleMap.put(rw.selectedRole, rw.selectedRole);
	        	usersList = [select Id, Name, User.UserRole.Name, User.Title, UserRoleId from User u where u.UserRoleId in :roleTitleMap.keySet() limit 1000];
	    	}
        	for(User u: usersList)
        	{
        		if(checkParticipantsMap.get(u.Id) == null)
        		{
	        		Plan_Assignable__c pa = new Plan_Assignable__c(Participant__c = u.Id, Role_ID__c = u.UserRoleId, Role_Title__c = u.UserRole.Name);
	        		participantsList.add(pa);
	        		checkParticipantsMap.put(u.Id, pa);
        		}
        		else
	        		participantsList.add(checkParticipantsMap.get(u.Id));
        		
        	}
			
			//Start : Remove all the Particpants whose Roles or Titles have been removed 
			List<Plan_Assignable__c> assignedParticipantsList = checkParticipantsMap.values();
			Boolean checkRemoveFlag = false;
			for(Plan_Assignable__c participant : assignedParticipantsList)
			{
				checkRemoveFlag = false;
				for(Plan_Assignable__c pa : participantsList)
				{
					if(pa.Participant__c == participant.Participant__c)
					{
						checkRemoveFlag = !checkRemoveFlag;
						break;
					}
				}
				if(!checkRemoveFlag)
					checkParticipantsMap.remove(participant.Participant__c);	
			}
			//End : Remove all the Particpants whose Roles or Titles have been removed
			
	        if(participantsList != null && participantsList.size() == 0)
	        	participantsList = null;
	        
    	}
    	catch(Exception e)
    	{
    		ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.info, e.getMessage()));
    	}
    	
    	return null;
    }

    public PageReference removeEligibility()
    {
    	try
    	{
	    	Integer count = 0;
	    	
	        if(byRoleTitle == 'byRole' && rolesList.size() > 0)
	        {
	            for(RoleWrapper rw: rolesList)
	            {
	                if(rw.roleNumber == removeEligibilityRow)
	                {
			            rolesList.remove(count);
			            break;
	                }
			        count++;
	            }
	        }
	        else if(titlesList.size() > 0)
	        {
	            for(TitleWrapper tw: titlesList)
	            {
	                if(tw.titleNumber == removeEligibilityRow)
	                {
			            titlesList.remove(count);
			            break;
	                }
	                count++;
	            }
	        }
	        
    	}
    	catch(Exception e)
    	{
    		ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, e.getMessage()));
    	}
        return null;
    }    

    public PageReference checkSelection()
    {
    	try
    	{
	        if(byRoleTitle == 'byTitle')
	        {
	            for(RoleWrapper ur: rolesList)
	                rolesDupList.add(ur);
	            rolesList.clear();
	            if(titlesDupList.size() > 0)
	            {
	                for(TitleWrapper u: titlesDupList)
	                    titlesList.add(u);
	                titlesDupList.clear();
	            }
	            
	        }
	        else
	        {
	            for(TitleWrapper u: titlesList)
	                titlesDupList.add(u);
	            titlesList.clear();
	            
	            if(rolesDupList.size() == 0 && rolesList.size() == 0)
	            {
		            rolesList.add(new RoleWrapper(roleCount++));
		            rolesList.add(new RoleWrapper(roleCount++));
		            rolesList.add(new RoleWrapper(roleCount++));
		            rolesList.add(new RoleWrapper(roleCount++));
		            rolesList.add(new RoleWrapper(roleCount++));
	            }
	            
	            if(rolesDupList.size() > 0)
	            {
	                for(RoleWrapper ur: rolesDupList)
	                    rolesList.add(ur);
	                rolesDupList.clear();
	            }
	        }
    	}
    	catch(Exception e)
    	{
    		ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, e.getMessage()));
    	}
        return null;
    }    
    
    public class RoleWrapper 
    {
        public ID selectedRole {get; set;}
        public Integer roleNumber {get; set;}

        public RoleWrapper(Integer roleNumber)
        {
        	this.roleNumber = roleNumber;
        }

        public List<SelectOption> getRoles() 
        {
            List<SelectOption> options = new List<SelectOption>();
            
            //options.add(new SelectOption('select', 'Select'));
            for(UserRole[] uRoleList: [select Id, Name from UserRole order by Name])
            {
                for(UserRole ur: uRoleList)
                    options.add(new SelectOption(ur.Id, ur.Name));
                if(options.size() >= 1000)
                    break;
            }
            return options; 
        }
    }
    
    public List<RoleWrapper> getRoleRows() {
        return rolesList;
    }

    public class TitleWrapper 
    {
        public String selectedTitle {get; set;}
        public Integer titleNumber {get; set;}

       /* private List<String> localTitleList = null;
        public TitleWrapper()
        {
            //localTitleList = EditPlanEligibilityVF.userTitleList.deepClone();
        }*/
        
        public titleWrapper(Integer titleNumber)
        {
        	this.titleNumber = titleNumber;
        }
        
        public List<SelectOption> getTitles() 
        {
            List<SelectOption> options = new List<SelectOption>();
            
            //options.add(new SelectOption('select', 'Select'));
            Map<String, String> tempUserMap = new Map<String, String>(); 
            for(User[] usersList: [select Title from User where Title != ''])
            {
                for(User u: usersList)
                    tempUserMap.put(u.Title, u.Title);
                if(tempUserMap.size() >= 1000)
                    break;
            }
            List<String> titlesList = tempUserMap.values();
            
            for(String s: titlesList)
                options.add(new SelectOption(s, s));

            return options; 
        }
    }
    
    public List<TitleWrapper> getTitleRows() {
        return titlesList;
    }
}